name: BPF Checks

# Any change in triggers needs to be reflected in the concurrency group.
on:
  pull_request: {}
  push:
    branches:
      - main
      - ft/main/**
  merge_group:
    types: [checks_requested]

permissions: read-all

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.after || github.event.merge_group && github.run_id }}
  cancel-in-progress: ${{ !github.event.merge_group }}

jobs:
  check_changes:
    name: Deduce required tests from code changes
    runs-on: ubuntu-latest
    outputs:
      bpf-tree: ${{ steps.changes.outputs.bpf-tree }}
      coccinelle: ${{ steps.changes.outputs.coccinelle }}
      bpf-tests-runner: ${{ steps.changes.outputs.bpf-tests-runner }}
      workflow-description: ${{ steps.changes.outputs.workflow-description }}
    steps:
      - name: Checkout code
        if: ${{ !github.event.pull_request }}
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
      - name: Check code changes
        uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
        id: changes
        with:
          # For `push` events, compare against the `ref` base branch
          # For `pull_request` events, this is ignored and will compare against the pull request base branch
          base: ${{ github.ref }}
          filters: |
            bpf-tree:
              - 'bpf/**'
            coccinelle:
              - 'contrib/coccinelle/**'
            bpf-tests-runner:
              - 'test/bpf_tests/**'
              - 'pkg/bpf/**'
            workflow-description:
              - '.github/workflows/lint-bpf-checks.yaml'

  checkpatch:
    name: Check Patch
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          fetch-depth: 0
      - name: Run checkpatch.pl
        run: |
          make -C bpf checkpatch || (echo "Run 'make -C bpf checkpatch' locally to investigate reports"; exit 1)

  # Runs only if code under bpf/ or contrib/coccinnelle/ is changed.
  coccicheck:
    needs: check_changes
    if: ${{ needs.check_changes.outputs.bpf-tree == 'true' || needs.check_changes.outputs.coccinelle == 'true' || needs.check_changes.outputs.workflow-description == 'true' }}
    name: Run coccicheck
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
      - name: Run coccicheck
        uses: docker://cilium/coccicheck:2.4@sha256:24abe3fbb8e829fa41a68a3b76cb4df84fd5a87a7d1d6254c1c1fe5effb5bd1b
        with:
          entrypoint: ./contrib/coccinelle/check-cocci.sh
        # Note: Setting COCCINELLE_HOME can be removed, here and in the
        # messages in the .cocci files, next time we upgrade coccinelle.
        # The issue was fixed, after v1.1.1 that we're using, in
        # https://gitlab.inria.fr/coccinelle/coccinelle/-/commit/540888ff426e.
        env:
          COCCINELLE_HOME: /usr/local/lib/coccinelle

  set_clang_dir:
    name: Set clang directory
    runs-on: ubuntu-latest
    outputs:
      clang_dir: ${{ steps.set_dir.outputs.clang_dir }}
    steps:
    - name: Set directory
      id: set_dir
      run: echo "clang_dir=$HOME/.clang" >> $GITHUB_OUTPUT

  # Runs only if code under bpf/ is changed.
  build_all:
    needs: [check_changes, set_clang_dir]
    if: ${{ needs.check_changes.outputs.bpf-tree == 'true' || needs.check_changes.outputs.workflow-description == 'true' }}
    name: Build Datapath
    runs-on: ubuntu-22.04
    steps:
      - name: Install Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          # renovate: datasource=golang-version depName=go
          go-version: 1.22.0
      - name: Cache LLVM and Clang
        id: cache-llvm
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        with:
          path: ${{ needs.set_clang_dir.outputs.clang_dir }}
          key: llvm-10.0
      - name: Install LLVM and Clang prerequisites
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends libtinfo5
      - name: Install LLVM and Clang
        uses: KyleMayes/install-llvm-action@be40c5af3a4adc3e4a03199995ab73aa37536712 # v1.9.0
        with:
          version: "10.0"
          directory: ${{ needs.set_clang_dir.outputs.clang_dir }}
          cached: ${{ steps.cache-llvm.outputs.cache-hit }}
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          fetch-depth: 0
      - name: Build all BPF datapath permutations
        env:
          V: 0
        run: |
          make --quiet -C bpf build_all || (echo "Run 'make -C bpf build_all' locally to investigate build breakages"; exit 1)

  bpf_tests:
    needs: [check_changes, set_clang_dir]
    if: ${{ needs.check_changes.outputs.bpf-tree == 'true' || needs.check_changes.outputs.bpf-tests-runner == 'true' || needs.check_changes.outputs.workflow-description == 'true' }}
    name: BPF unit/integration Tests
    runs-on: ubuntu-22.04
    steps:
      - name: Install Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          # renovate: datasource=golang-version depName=go
          go-version: 1.22.0
      - name: Cache LLVM and Clang
        id: cache-llvm
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        with:
          path: ${{ needs.set_clang_dir.outputs.clang_dir }}
          key: llvm-10.0
      - name: Install LLVM and Clang prerequisites
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends libtinfo5
      - name: Install LLVM and Clang
        uses: KyleMayes/install-llvm-action@be40c5af3a4adc3e4a03199995ab73aa37536712 # v1.9.0
        with:
          version: "10.0"
          directory: ${{ needs.set_clang_dir.outputs.clang_dir }}
          cached: ${{ steps.cache-llvm.outputs.cache-hit }}
      - name: Checkout code
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          fetch-depth: 0
      - name: Run BPF tests
        run: |
          make -C test run_bpf_tests || (echo "Run 'make -C test run_bpf_tests' locally to investigate failures"; exit 1)
